package manager

import (
	"fmt"
	"gitee.com/huanminabc/go-utils/code_analysis"
	"gitee.com/huanminabc/go-utils/vars"
	"go-CodeAnalysis/expression"
	"go-LineScriptCommand/container"
	"go-LineScriptCommand/global"
	"runtime/debug"
	"strconv"
	"strings"
)

func CoreExecuteTest(str string) string {
	container.ClearPipelineData() //清理管道数据
	execute := CoreExecute(str)
	fmt.Println(execute) //输出结果到控制台
	return execute
}

func CoreExecuteClean(str string) string {
	container.ClearPipelineData() //清理管道数据
	execute := CoreExecute(str)
	return execute
}

func CodeRun(code string) string {
	//判断是否是空函数
	fun := container.IsExistFun(code) //如果这个返回true,那么就是函数
	if fun {
		return container.ExecuteFun(code, []string{}...)
	}
	//判断是否是函数,如果是函数,那么就执行函数
	cut := container.ExecuteFunCut(code)
	if cut != "%^%^%^%" {
		return cut
	}
	//计算表达式
	tokens := code_analysis.CodeToTokens(code)
	if IsExpression(tokens) {
		return expression.CalculateCore(tokens)
	}
	return code
}

// 换行符替换
func LineBreakReplace(v string) string {
	//如果存在\r\n ,那么就替换为自定义的换行符
	if strings.Contains(v, "\r\n") {
		v = strings.Replace(v, "\r\n", global.LineBreak, -1)
	}
	if strings.Contains(v, "\\r\\n") {
		v = strings.Replace(v, "\\r\\n", global.LineBreak, -1)
	}

	//如果存在\n ,那么就替换为自定义的换行符
	if strings.Contains(v, "\\n") {
		v = strings.Replace(v, "\\n", global.LineBreak, -1)
	}
	if strings.Contains(v, "\n") {
		v = strings.Replace(v, "\n", global.LineBreak, -1)
	}
	//如果存在\r ,那么就替换为空, 因为现在平台都只支持\n了,\r可有可无
	if strings.Contains(v, "\\r") {
		v = strings.Replace(v, "\\r", "", -1)
	}
	if strings.Contains(v, "\r") {
		v = strings.Replace(v, "\r", "", -1)
	}
	return v
}

func CoreExecute(str string) string {
	defer func() {
		if err := recover(); err != nil {
			errorMess := fmt.Sprintf("%s", err)
			fmt.Println(vars.RedColor("错误: " + errorMess))
			fmt.Println("执行的命令: " + str)
			debug.PrintStack() // 打印堆栈信息
			//管道内容打印
			fmt.Println(vars.RedColor("===================管道内容==================="))
			for i, v := range container.PipelineDataSlice {
				fmt.Println(i, " -> ", v.Data)
			}
		}
	}()
	global.ExpressionPipe = str

	//将字符串全部转换为"
	str = strings.Replace(str, "'", "\"", -1)

	//0.提取全部字符串
	both, strOld := code_analysis.PickBoth(str, global.StrSplitSymbol)

	//1.先以|分割,获取每个命令
	strs := strings.Split(strOld, "|")
	for _, v := range strs {

		//去空(前后)
		v = strings.TrimSpace(v)
		//如果v为空,那么就跳过
		if v == "" {
			continue
		}

		//1.转换管道参数
		v = transitionPipelineParam(v)

		//2.还原pickBoth的字符串字符串
		v = code_analysis.RestorePickBoth(v, both)

		//如果存在\r\n ,那么就替换为自定义的换行符
		v = LineBreakReplace(v)

		//判断是否是函数
		fun := container.IsExistFun(v) //如果这个返回true,那么就是函数
		//如果是函数,那么就执行函数
		if fun {
			executeFun := container.ExecuteFun(v, []string{}...)
			if global.StopPipe {
				return global.StopSign
			}
			//将结果放入到管道中
			data := container.NewPipelineData(executeFun)
			container.RegisterPipelineData(data)
			continue
		}
		//判断是否是函数,如果是函数,那么就执行函数
		cut := container.ExecuteFunCut(v)
		if global.StopPipe {
			return global.StopSign
		}
		if cut != "%^%^%^%" {
			//将结果放入到管道中
			data := container.NewPipelineData(cut)
			container.RegisterPipelineData(data)
			continue
		}
		var value string
		tokens := code_analysis.CodeToTokens(v)
		if IsExpression(tokens) {
			//计算表达式
			value = expression.CalculateCore(tokens)
		} else {
			value = v
		}
		//返回结果到管道中
		data := container.NewPipelineData(value)
		container.RegisterPipelineData(data)

	}
	//返回最后一个管道的结果
	if container.GetPrePipelineData().Data != "" {
		result := container.GetPrePipelineData().Data
		//如果是字符串,那么就去掉双引号
		result = global.RemoveStrSymbol(result)
		//输出一律替换为\n 这样才能兼容多系统
		result = strings.Replace(result, global.LineBreak, "\n", -1)
		return result
	}
	return global.StopSign

}

// 遍历SymbolGroup然后判断是否是表达式
func IsExpression(token []code_analysis.Token) bool {
	//判断是否存在符号
	if len(token) == 0 {
		return false
	}
	//OPERATOR
	for _, v := range token {
		if v.Type == code_analysis.OPERATOR {
			return true
		}
	}
	return false
}

// 将管道参数转换为实际值
// 1.$$表示获取上一个命令的结果
// 2.如果是$1,$2表示获取第一个,第二个参数
func transitionPipelineParam(param string) string {
	//判断包含## 并且管道不为空
	if strings.Contains(param, "##") && container.GetPrePipelineData().Data == "" {
		panic("管道为空,不能使用##")
	}
	if strings.Contains(param, "##") && container.GetPrePipelineData().Data != "" {
		str := container.GetPrePipelineData().Data
		param = strings.Replace(param, "##", str, -1)
		return transitionPipelineParam(param)
	}

	//或者#1,#2...
	if strings.Contains(param, "#") {
		dollar := code_analysis.GetStrSharp(param)
		if dollar != "" {
			index, _ := strconv.Atoi(dollar[1:])
			if container.GetPipelineData(index).Data == "" {
				panic(dollar + "参数为空,找不到值")
			}
			s := container.GetPipelineData(index).Data
			//替换#1,#2...
			param = strings.Replace(param, dollar, s, 1)
			return transitionPipelineParam(param)
		}
	}
	return param

}
